#include "nosal/log/logger.h"
#include "slog2/common.h"
#include "slog2/slog2_context.h"

namespace netaos {
namespace nosal {
namespace log {

namespace {
Slog2Context* toSlog2Context(void* context) noexcept
{
    return static_cast<Slog2Context*>(context);
}

Slog2VerbosityLevel toSlog2VerbosityLevel(LogLevel loglevel)
{
    Slog2VerbosityLevel verbosity_level = Slog2VerbosityLevel::kShutdown;
    switch (loglevel)
    {
        case LogLevel::kFatal:
            verbosity_level = Slog2VerbosityLevel::kCritical;
            break;
        case LogLevel::kError:
            verbosity_level = Slog2VerbosityLevel::kError;
            break;
        case LogLevel::kWarn:
            verbosity_level = Slog2VerbosityLevel::kWarning;
            break;
        case LogLevel::kInfo:
            verbosity_level = Slog2VerbosityLevel::kInfo;//kNotice
            break;
        case LogLevel::kDebug:
            verbosity_level = Slog2VerbosityLevel::kDebug1;
            break;
        case LogLevel::kVerbose:
            verbosity_level = Slog2VerbosityLevel::kDebug2;
           break;
        default:
            verbosity_level = Slog2VerbosityLevel::kShutdown;
            break;
    }
    return verbosity_level;
}

} // namespace

Logger::Logger(std::string context_id,
	       	std::string description,
	       	LogLevel default_loglevel)
    : context_id_{context_id}
    , description_{description}
    , default_loglevel_{default_loglevel}
{ 
    logcontext_ = static_cast<void*>(new Slog2Context);
    toSlog2Context(logcontext_)->Initialize(context_id, description,
		    toSlog2VerbosityLevel(default_loglevel));
    is_initialized_ = true;
}

Logger::~Logger()
{
    deinitialize();
    delete toSlog2Context(logcontext_);
}

LogStream Logger::LogFatal() const noexcept
{
    return {LogLevel::kFatal, *this};
}

LogStream Logger::LogError() const noexcept
{
    return {LogLevel::kError, *this};
}

LogStream Logger::LogWarn() const noexcept
{
    return {LogLevel::kWarn, *this};
}

LogStream Logger::LogInfo() const noexcept
{
    return {LogLevel::kInfo, *this};
}

LogStream Logger::LogDebug() const noexcept
{
    return {LogLevel::kDebug, *this};
}

LogStream Logger::LogVerbose() const noexcept
{
    return {LogLevel::kVerbose, *this};
}

LogStream Logger::WithLevel(LogLevel loglevel) const noexcept
{
    return {loglevel, *this};
}

bool Logger::IsEnabled(LogLevel loglevel) const noexcept
{
    return loglevel <= default_loglevel_;
}

void* Logger::getContext() const noexcept
{
    return logcontext_;
}

void Logger::deinitialize() noexcept
{
    if (is_initialized_) {
        is_initialized_ = false;
    }
}

void Logger::enableConsole(bool enable) noexcept
{
    toSlog2Context(logcontext_)->EnableConsole(enable);	
}

void Logger::enableRemote(bool enable) noexcept
{
    toSlog2Context(logcontext_)->EnableRemote(enable);	
}

}  // namespace log
}  // namespace nosal
}  // namespace netaos
